package org.nlp.algo.LeastSquareMethod;


/**
 * 最小二乘法
 * 
 * @author Administrator
 * 
 */
public class LeastSquareMethod {
	private double[] x;
	private double[] y;
	private double[] weight;
	private int m;
	private double[] coefficient;
	public LeastSquareMethod(double[] x, double[] y, int m) {
		if (x == null || y == null || x.length < 2 || x.length != y.length
				|| m < 2)
			throw new IllegalArgumentException("无效的参数");
		this.x = x;
		this.y = y;
		this.m = m;
		weight = new double[x.length];
		for (int i = 0; i < x.length; i++) {
			weight[i] = 1;
		}
	}
	public LeastSquareMethod(double[] x, double[] y, double[] weight, int m) {
		if (x == null || y == null || weight == null || x.length < 2
				|| x.length != y.length || x.length != weight.length || m < 2)
			throw new IllegalArgumentException("无效的参数");
		this.x = x;
		this.y = y;
		this.m = m;
		this.weight = weight;
	}
	public double[] getCoefficient() {
		if (coefficient == null)
			compute();
		return coefficient;
	}
	public double fit(double v) {
		if (coefficient == null)
			compute();
		if (coefficient == null)
			return 0;
		double sum = 0;
		for (int i = 0; i < coefficient.length; i++) {
			sum += Math.pow(v, i) * coefficient[i];
		}
		return sum;
	}
	private void compute() {
		if (x == null || y == null || x.length <= 1 || x.length != y.length
				|| x.length < m || m < 2)
			return;
		double[] s = new double[(m - 1) * 2 + 1];
		for (int i = 0; i < s.length; i++) {
			for (int j = 0; j < x.length; j++)
				s[i] += Math.pow(x[j], i) * weight[j];
		}
		double[] f = new double[m];
		for (int i = 0; i < f.length; i++) {
			for (int j = 0; j < x.length; j++)
				f[i] += Math.pow(x[j], i) * y[j] * weight[j];
		}
		double[][] a = new double[m][m];
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < m; j++) {
				a[i][j] = s[i + j];
			}
		}
		coefficient = Algorithm.multiLinearEquationGroup(a, f);
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		LeastSquareMethod l = new LeastSquareMethod(
				new double[] { 2000, 2001, 2002}, 
				new double[] { 0, 2, 3}, 
				new double[] { 1, 23, 49},
				2);
		double[] x = l.getCoefficient();
		for (double xx : x) {
			System.out.println(xx);
		}
		System.out.println(l.fit(2001));
	}
}
                        
